package com.imooc.service.impl;


import com.imooc.BO.ShopCartBO;
import com.imooc.utils.DateUtil;
import com.imooc.vo.MerchantOrdersVO;
import com.imooc.BO.SubmitOrderBO;
import com.imooc.enums.OrderStatusEnum;
import com.imooc.enums.YesOrNo;
import com.imooc.mapper.OrderItemsMapper;
import com.imooc.mapper.OrderStatusMapper;
import com.imooc.mapper.OrdersMapper;
import com.imooc.pojo.*;
import com.imooc.service.AddressService;
import com.imooc.service.ItemsService;
import com.imooc.service.OrderService;
import com.imooc.vo.OrderVO;
import org.n3r.idworker.Sid;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author gcq
 * @Create 2022-01-08
 */
@Service
public class OrderServiceImpl implements OrderService {

    private Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

    @Autowired
    OrdersMapper ordersMapper;

    @Autowired
    AddressService addressService;

    @Autowired
    ItemsService itemsService;

    @Autowired
    OrderItemsMapper orderItemsMapper;

    @Autowired
    OrderStatusMapper orderStatusMapper;

    @Autowired
    Sid sid;

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public OrderVO createOrder(SubmitOrderBO submitOrderBO, List<ShopCartBO> shopCartList) {
        String userId = submitOrderBO.getUserId();
        String addressId = submitOrderBO.getAddressId();
        String itemSpecIds = submitOrderBO.getItemSpecIds();
        Integer payMethod = submitOrderBO.getPayMethod();
        String leftMsg = submitOrderBO.getLeftMsg();

        Integer postAmount = 0;
        String orderId = sid.nextShort();

        // 1、新订单保存
        Orders orders = new Orders();
        orders.setId(orderId);
        orders.setUserId(userId);

        UserAddress address = addressService.queryUserAddress(userId, addressId);

        orders.setReceiverName(address.getReceiver());
        orders.setReceiverMobile(address.getMobile());
        orders.setReceiverAddress(address.getProvince() + " "
                                  + address.getCity() + " "
                                  + address.getDistrict() + " "
                                  + address.getDetail());

        // 邮费
        orders.setPostAmount(postAmount);

        orders.setPayMethod(payMethod);
        orders.setLeftMsg(leftMsg);
        orders.setIsComment(YesOrNo.NO.type);
        orders.setIsDelete(YesOrNo.NO.type);
        orders.setCreatedTime(new Date());
        orders.setUpdatedTime(new Date());

        // 2、循环根据itemsSpecId 保存订单商品信息表
        String[] itemSpecIdArr = itemSpecIds.split(",");
        // 商品原价累计
        Integer totalAmount = 0;
        // 优惠后实际支付价格累计
        Integer realPayAmount = 0;
        List<ShopCartBO> shopCartBOList = new ArrayList<>();
        for (String itemSpecId : itemSpecIdArr) {
            // 从 redis 中获取购物车中商品
            // TODO 整合 redis 商品购买数量重新从 redis 的购物车中获取
            ShopCartBO shopCart = this.getBuyCountsFromShopCart(shopCartList, itemSpecId);
            shopCartBOList.add(shopCart);

            int buyCounts = shopCart.getBuyCounts();

            // 2.1、根据商品规格 Id 查询规格的具体信息，主要获取价格
            ItemsSpec itemsSpec = itemsService.queryItemsSpecById(itemSpecId);
            totalAmount += itemsSpec.getPriceDiscount() * buyCounts;
            realPayAmount += itemsSpec.getPriceDiscount() *  buyCounts;

            //  2.2、根据商品 Id,获得商品信息以及商品图片
            String itemId = itemsSpec.getItemId();
            Items item = itemsService.queryItemById(itemId);
            String imgUrl = itemsService.queryItemMainImgById(itemId);

            // 2.3、循环保存子订单数据到数据库
            String subOrderId = sid.nextShort();
            OrderItems subOrderItem = new OrderItems();
            subOrderItem.setItemId(item.getId());
            subOrderItem.setId(subOrderId);
            subOrderItem.setItemName(item.getItemName());
            subOrderItem.setOrderId(orderId);
            subOrderItem.setBuyCounts(buyCounts);
            subOrderItem.setPrice(itemsSpec.getPriceDiscount());
            subOrderItem.setItemSpecId(itemSpecId);
            subOrderItem.setItemSpecName(itemsSpec.getName());
            subOrderItem.setItemImg(imgUrl);
            orderItemsMapper.insert(subOrderItem);

            // 2.4、用户提交订单后，规格表中需要扣除库存
            itemsService.decreaseItemSpecStock(itemSpecId, buyCounts);
        }
        // 订单总价格
        orders.setTotalAmount(totalAmount);
        // 订单支付总价格
        orders.setRealPayAmount(realPayAmount);
        ordersMapper.insert(orders);

        // 3、保存订单状态表
        OrderStatus orderStatus = new OrderStatus();
        orderStatus.setOrderId(orderId);
        orderStatus.setOrderStatus(OrderStatusEnum.WAIT_PAY.type);
        orderStatus.setCreatedTime(new Date());
        orderStatusMapper.insert(orderStatus);

        // 4、构建商户订单，用于传给支付中心
        MerchantOrdersVO merchantOrdersVO = new MerchantOrdersVO();
        merchantOrdersVO.setMerchantOrderId(orderId);
        merchantOrdersVO.setMerchantUserId(userId);
        merchantOrdersVO.setAmount(realPayAmount + postAmount);
        merchantOrdersVO.setPayMethod(payMethod);

        // 5、构建自定义订单VO

        OrderVO orderVO = new OrderVO();
        orderVO.setOrderId(orderId);
        orderVO.setMerchantOrdersVO(merchantOrdersVO);
        orderVO.setToBeRemovedShopCartList(shopCartBOList);
        return orderVO;
    }

    /**
     * 根据 SpecId 从购物车中获取到对应商品的数据
     *
     * @param shopCartList 购物车列表
     * @param specId 规格Id
     * @return specId 对应的购物项 或者 null
     */
    private ShopCartBO getBuyCountsFromShopCart(List<ShopCartBO> shopCartList, String specId) {
        for (ShopCartBO cart : shopCartList) {
            if(cart.getSpecId().equals(specId)) {
                return cart;
            }
        }
        return null;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void updateOrderStatus(String orderId, Integer orderStatus) {
        OrderStatus paidStatus = new OrderStatus();
        paidStatus.setOrderId(orderId);
        paidStatus.setOrderStatus(orderStatus);
        paidStatus.setPayTime(new Date());

        logger.info("**** 订单 {} 修改状态为 {}", orderId, orderStatus);
        orderStatusMapper.updateByPrimaryKeySelective(paidStatus);
    }

    @Override
    public OrderStatus queryOrderStatusInfo(String orderId) {
        OrderStatus orderStatus = new OrderStatus();
        orderStatus.setOrderId(orderId);
        return orderStatusMapper.selectOne(orderStatus);
    }

    @Transactional(propagation = Propagation.REQUIRED)
    @Override
    public void closeOrder() {
        // 查询所有未付款订单，判断时间是否超时（1天）超时关闭交易
        OrderStatus orderStatus = new OrderStatus();
        orderStatus.setOrderStatus(OrderStatusEnum.WAIT_PAY.type);
        List<OrderStatus> list = orderStatusMapper.select(orderStatus);
        for (OrderStatus status : list) {
            Date createdTime = status.getCreatedTime();
            int days = DateUtil.daysBetween(createdTime, new Date());
            if(days >= 1) {
                doCloseOrder(status.getOrderId());
            }
        }
    }

    @Transactional(propagation = Propagation.REQUIRED)
    void doCloseOrder(String orderId) {
        OrderStatus orderStatus = new OrderStatus();
        orderStatus.setOrderId(orderId);
        orderStatus.setOrderStatus(OrderStatusEnum.CLOSE.type);
        orderStatus.setCloseTime(new Date());
        orderStatusMapper.updateByPrimaryKeySelective(orderStatus);
    }
}